#ifndef __TCP_CLIENT_HPP__
#define __TCP_CLIENT_HPP__
#include "MyPthread/Log.hpp"
#include "Common.hpp"
#include "InetAddr.hpp"
#include "Protocol.hpp"
using namespace LogModule;

const static int gsockfd = -1;
class TcpClient
{
private:
public:
    TcpClient(std::string server_ip = gserver_ip, uint16_t server_port = gserver_port)
        : _sockfd(gsockfd), _server(server_ip, server_port)
    {
    }
    ~TcpClient()
    {
    }
    // 1. 创建socket
    void InitClient()
    {
        // 1. 创建socket
        _sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            LOG(LogLevel::ERROR) << "socket error";
            Die(SOCKET_ERR);
        }
        // 2. 连接
        // client 不需要显式地进行bind, tcp是面向连接的, connect 底层会自动进行bind
        int n = connect(_sockfd, _server.NetAddr(), _server.NetAddrLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "connect failed";
            Die(CONNECT_ERR);
        }
    }
    void Start()
    {

        while (true)
        {
            // std::cout << "Please Enter# ";
            std::string message;

            int x, y;
            char oper;
            std::cout << "input x: ";
            std::cin >> x;
            std::cout << "input y: ";
            std::cin >> y;
            std::cout << "input oper: ";
            std::cin >> oper;

            Request req(x, y, oper);

            // 1.序列化
            req.Serialize(message);

            // 2.封装报文添加头部
            Encode(message);

            // 3.发送报文
            int n = ::send(_sockfd, message.c_str(), message.size(), 0);
            (void)n;

            // LOG(LogLevel::DEBUG) << "send succeed:" << message;

            char inbuffer[1024];
            n = ::recv(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0);

            if (n > 0)
            {
                inbuffer[n] = 0;


                // 4.解析报文
                std::string out_string;
                std::string package = inbuffer;

                Decode(package, &out_string);

                // 5.反序列化
                Response res;
                res.Deserialize(out_string);

                // 6.打印结果       
                res.Print();

                // std::cout << inbuffer << std::endl;
            }
        }
    }

public:
private:
    int _sockfd;
    // struct sockaddr_in _client;
    InetAddr _server;
};

#endif